package com.canaan.common.utils;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.Scanner;

/**
 * License相关工具类
 */
public class LicenseUtil {

    private final static String systemCode = "wms";

    public static String getMotherboardInfo(){
        String macAddress = getMacAddress();
        String cpu = getCpuInfo();
        String hdsn = getHardDiskSerialNumber();
        String motherboardInfo = macAddress + cpu + hdsn + systemCode;
        return encryptMD5(motherboardInfo);
    }


    public static String getMemoryInfo() {
        return executeCommand("free -h");
    }

    public static String getDiskInfo() {
        return executeCommand("df -h");
    }

    public static String getOSInfo() {
        return executeCommand("cat /etc/os-release");
    }

    public static String getHostName() {
        return executeCommand("hostname");
    }

    public static String getCpuInfo() {
        String osName = System.getProperty("os.name");
        String cpuInfo = "";
        if (osName.startsWith("Linux")) {
            cpuInfo = executeCommand("cat /proc/cpuinfo");
        } else if (osName.startsWith("Windows")) {
            cpuInfo = executeCommand("wmic cpu get Name,NumberOfCores");
        }
        return cpuInfo;
    }

    public static String getMacAddress() {
        StringBuilder macAddresses = new StringBuilder();
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                byte[] mac = networkInterface.getHardwareAddress();
                if (mac != null) {
                    StringBuilder macAddress = new StringBuilder();
                    for (int i = 0; i < mac.length; i++) {
                        macAddress.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
                    }
                    macAddresses.append(networkInterface.getName()).append(": ").append(macAddress.toString()).append("\n");
                }
            }
        } catch (Exception e) {
        }
        return macAddresses.toString().trim();
    }

    /**
     * 获取硬盘序列号
     *
     * @return 硬盘序列号
     */
    public static String getHardDiskSerialNumber() {
        String sysName = System.getProperty("os.name");
        if (sysName.contains("Windows")) {//win
            String str = runCmd("wmic path win32_physicalmedia get serialnumber", 2);
            return str;
        } else if (sysName.contains("Linux")) {
            String str = runCmd("dmidecode |grep -A16 \"System Information$\"", "Serial Number");
            if (str != null) {
                return str.substring(str.indexOf(":")).trim();
            }
        } else if (sysName.contains("Mac")) {
            String str = runCmd("system_profiler SPStorageDataType", "Volume UUID");
            if (str != null) {
                return str.substring(str.indexOf(":") + 1).trim();
            }
        }
        return "";
    }

    private static String encryptMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            return "Error encrypting info";
        }
    }

    private static String executeCommand(String command) {
        StringBuilder output = new StringBuilder();
        try {
            Process process = Runtime.getRuntime().exec(command);
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }

            reader.close();
        } catch (IOException e) {
        }
        return output.toString();
    }/**
     * 运行cmd命令
     *
     * @param cmd    命令
     * @param substr 关键字
     * @return 包含关键字的行数
     */
    public static String runCmd(String cmd, String substr) {
        Process process;
        Scanner sc = null;
        try {
            process = Runtime.getRuntime().exec(cmd);
            process.getOutputStream().close();
            sc = new Scanner(process.getInputStream());
            while (sc.hasNextLine()) {
                String str = sc.nextLine();
                if (str != null && str.contains(substr)) {
                    return str.trim();
                }
            }
            sc.close();
        } catch (Exception e) {

        } finally {
            close(sc);
        }
        return null;
    }

    /**
     * 运行命令
     *
     * @param cmd  命令
     * @param line 返回第几行结果，0返回所有
     * @return 结果
     */
    public static String runCmd(String cmd, int line) {
        Process process;
        Scanner sc = null;
        StringBuffer sb = new StringBuffer();
        try {
            process = Runtime.getRuntime().exec(cmd);
            process.getOutputStream().close();
            sc = new Scanner(process.getInputStream());
            int i = 0;
            while (sc.hasNextLine()) {
                i++;
                String str = sc.nextLine();
                if (line <= 0) {
                    sb.append(str).append("\r\n");
                } else if (i == line) {
                    return str.trim();
                }
            }
            sc.close();
        } catch (Exception e) {


        } finally {
            close(sc);
        }
        return sb.toString();
    }

    /**
     * 关闭流
     *
     * @param outs Closeable
     */
    public static void close(Closeable... outs) {
        if (outs != null) {
            for (Closeable out : outs) {
                if (out != null) {
                    try {
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
